<?php
declare (strict_types=1);

namespace app\common\model;

use app\common\facade\Target;
use app\common\tool\pay\Pay;
use app\common\tool\Target\Driver\Account;
use think\facade\Cache;
use think\facade\Event;

class Order extends Base
{
    protected $name = 'order';

    public function user()
    {
        return $this->hasOne(User::class, 'id', 'uid')->field('id,code,nickname,mobile');
    }

    public function address()
    {
        return $this->hasOne(Address::class, 'id', 'address_id');
    }

    public function express()
    {
        return $this->hasOne(Express::class, 'id', 'express_id');
    }

    public function p()
    {
        return $this->hasOne(Area::class, 'code', 'province')->field('code,province as title');
    }

    public function c()
    {
        return $this->hasOne(Area::class, 'code', 'city')->field('code,city as title');
    }

    public function d()
    {
        return $this->hasOne(Area::class, 'code', 'district')->field('code,district as title');
    }

    public function t()
    {
        return $this->hasOne(Area::class, 'code', 'town')->field('code,town as title');
    }

    public function products()
    {
        return $this->hasMany(OrderProduct::class, 'order_id');
    }

    public function getPayWayAttr($value)
    {
        return get_pay_way($value);
    }

    public function getStatusAttr($value)
    {
        return getOrderStatus($value);
    }

    public function getPostTimeAttr($value)
    {
        return $value ? date('Y-m-d H:i:s', $value) : '未发货';
    }

    public static function getTakeOverTableList($that, $param, $filed = '*', $count = 0)
    {
        try {
            foreach ($that as &$v) {
                $products = $v->products()->field('pid,product_title,num')->select()->toArray();
                foreach ($products as $item) {
                    $v->product .= $item['product_title'] . ' ' . '数量：' . $item['num'] . "\n";
                }
                $v->pay_time = $v->pay_time ? date('Y-m-d H:i:s', intval($v->pay_time)) : '待付款';
                $v->statusRaw = $v->getData('status');
            }
            return ['code' => 0, 'data' => $that, 'count' => $count];
        } catch (\Exception $e) {
            return [];
        }
    }


    /**
     * @param $param -- 提交的参数
     * @param $admin -- 后台当前登录管理员
     * @return array
     * 原点 2022年1月8日16:45:49 后台发货订单
     */
    public static function deliver($param, $admin)
    {

        try {
            $info = parent::find($param['id']);
            if ($info->isEmpty()) {
                return ['code' => -1, 'msg' => '未查询到相关订单'];
            }
            $status = $info->status;
            $info->express_id = $param['express_id'];
            $info->express_code = $param['express_code'];
            $info->receiver = $param['receiver'];
            $info->receiver_tel = $param['receiver_tel'];
            $info->province = $param['province'];
            $info->city = $param['city'];
            $info->district = $param['district'];
            $info->town = $param['town'];
            $info->address_details = $param['address_details'];
            $info->post_remark = $param['post_remark'];
            $info->post_time = time();

            $info->status = 3;
            $res = $info->save();
            if ($res !== true) {
                return ['code' => -1, 'msg' => '发货失败'];
            }
            if ($status < 3) {
                $msg = '订单发货，订单号【' . $info->sn . '】下单会员【' . $info->user->code . '】';
                $m = '已发货';
            } else {
                $msg = '修改了发货信息，订单号【' . $info->sn . '】下单会员【' . $info->user->code . '】';
                $m = '已修改';
            }

            Logs::adds($msg, $admin->id, $admin->admin_name);
            return ['code' => 1, 'msg' => $m];

        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * @param $uid -- 会员ID
     * @return array
     * 原点 2022年1月8日16:45:24 获得会员临时暂存的订单
     */
    public static function getTemporary($uid): array
    {
        try {
            $temporary = Cache::get('tsOrder_' . $uid);
            if (empty($temporary)) {
                return ['code' => -1, 'msg' => '加载失败'];
            }
            $infos = json_decode($temporary, true);
            $total = 0;
            $cate_1 = '';
            $products = [];
            foreach ($infos as $value) {
                $product = Product::where(['is_del' => 0, 'status' => 1, 'id' => $value['pid']])
                    ->field('id,title,price,icon,stock')->find();
                if (empty($product) || $product->stock <= 0) continue;
                $total += $product->price * $value['num'];
                $product->num = $value['num'];
                if (!$cate_1) $cate_1 = $value['cate_1'];
                $products[] = $product;
            }
            return [
                'products' => $products,
                'total'    => sprintf('%.2f', $total),
                'cate_1'   => $cate_1,
                'address'  => Address::getDefault($uid)
            ];
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * @param $address_id -- 选择地址ID
     * @param $user -- 会员信息
     * @return array
     * 原点 2022年1月8日16:44:54 提交产生待支付订单
     */
    public static function submit($address_id, $user): array
    {
        if (!$address_id) {
            return ['code' => -1, 'msg' => '请选择收货地址'];
        }
        $address = Address::where('id', $address_id)->find();
        if (empty($address)) {
            return ['code' => -1, 'msg' => '收货地址错误，请重新选择'];
        }
        $temporary = self::getTemporary($user->id);
        if (empty($temporary) || empty($temporary['products'])) {
            return ['code' => -1, 'msg' => '加载失败，请稍后再试'];
        }
        if (!$temporary['total'] || $temporary['total'] <= 0) {
            return ['code' => -1, 'msg' => '订单价格错误！'];
        }
        parent::startTrans();
        try {
            $new = parent::create([
                'sn'              => date('Ymd') . $user->id . time(),
                'uid'             => $user->id,
                'address_id'      => $address_id,
                'total_amount'    => $temporary['total'],
                'real_amount'     => $temporary['total'],
                'order_type'      => $temporary['cate_1'],
                'receiver'        => $address->nickname,
                'receiver_tel'    => $address->tel,
                'province'        => $address->province,
                'city'            => $address->city,
                'district'        => $address->district,
                'town'            => $address->town,
                'address_details' => $address->details,
            ]);

            $flag = OrderProduct::add($temporary['products'], $new->id);
            if ($flag['code'] != 1) {
                parent::rollback();
                return ['code' => -1, 'msg' => $flag['msg']];
            }

            parent::commit();
            Cart::clearCart($user->id);
            Cache::set('nowOrderId_' . $user->id, $new->id);
            return ['code' => 4, 'msg' => '已生成订单', 'url' => url('order/payment')->build()];
        } catch (\Exception $e) {
            parent::rollback();
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * @param $uid -- 会员ID
     * @return array
     * 原点 2022年1月8日16:44:08 获取当前会员待支付的订单
     * 每个会员同时只能下一个单，如有多个会替换掉！
     */
    public static function getNowOrder($uid): array
    {
        $now_id = Cache::get('nowOrderId_' . $uid);
        if (!$now_id) {
            return ['code' => -1, 'msg' => '加载失败'];
        }
        $info = parent::where(['id' => $now_id, 'uid' => $uid, 'status' => 1, 'pay_state' => 0])->find();
        if (empty($info)) {
            return ['code' => -1, 'msg' => '订单不存在或已支付'];
        }
        return ['code' => 1, 'result' => $info];
    }

    /**
     * @param $param -- 支付提交参数
     * @param $user -- 会员信息
     * @return array
     * 原点 2022年1月8日16:42:30 确认支付
     */
    public static function confirmPayment($param, $user): array
    {
        $info = self::getNowOrder($user->id);
        if ($info['code'] != 1) return $info;
        $order = $info['result'];

        $account = $param['pay_way'];

        $return_url = 'http://' . $_SERVER['HTTP_HOST'] . '/index/order/my_order?state=2';
        switch ($account) {
            case "currency":
            case "bonus":
                if ($user->assets->$account < $order->real_amount) {
                    return ['code' => -1, 'msg' => '账户余额不足'];
                }
                return self::operation($order, $user, $account);
            case "wechat":
                return ['code' => -1, 'msg' => '暂未开放'];
                $notifyUrl = 'http://' . $_SERVER['HTTP_HOST'] . '/index/callback/weChatOrder';
                //设置参数
                $payPreset = PayPreset::Instance()->setSubject('购买商品')
                    ->setOutTradeNo($order->sn)
                    ->setTotal($order->real_amount)
                    ->setTradeType('MWEB')
                    ->setNotifyUrl($notifyUrl)
                    ->setReturnUrl($return_url);
                //发起支付
                return Pay::WeChatPayV2($payPreset);
            case "alipay":
                $notifyUrl = 'http://' . $_SERVER['HTTP_HOST'] . '/index/callback/aliPayOrder';
                //设置参数
                $payPreset = PayPreset::Instance()->setSubject('购买商品')
                    ->setOutTradeNo($order->sn)
                    ->setTotal($order->real_amount)
                    ->setNotifyUrl($notifyUrl)
                    ->setReturnUrl($return_url);
                //发起支付
                return Pay::AliPayWeb($payPreset);

            default:
                return ['code' => -1, 'msg' => '请选择支付方式'];
        }

    }

    /**
     * @param $order -- 订单信息
     * @param $user -- 会员信息
     * @param $pay_way -- 支付方式
     * @return array
     * 原点 2022年1月8日16:42:02 支付完成后续操作
     */
    public static function operation($order, $user, $pay_way)
    {
        parent::startTrans();
        try {
            //其他后续操作，按需执行

            //更改状态
            $order->pay_state = 2;
            $order->pay_way = $pay_way;
            $order->pay_time = time();
            $order->status = 2;
            $order->save();

            //扣钱
            if (!in_array($pay_way, ['wechat', 'alipay'])) {
                Target::Account()
                    ->basics($user->id, $pay_way, $order->real_amount, '购买产品', '-')
                    ->createNormal($order->id);
            }

            switch ($order->order_type) {
                case 1://报单专区
                    $user->my_total = $user->my_total + $order->real_amount;
                    if ($user->is_active == 1) {
                        $user->is_active = 2;
                        $user->level_id = 1;
                        $user->active_time = time();
                    }
                    $user->save();

                    Relation::renewTeamTotal($order->real_amount, $user->id);

                    Event::trigger('Statistics', ['key' => 'income', 'value' => $order->real_amount]);

                    break;

                case 2://复消专区
                    break;
                default:
//                    parent::rollback();
//                    return ['code' => -1, 'msg' => '加载失败'];
            }
            Event::trigger('Operation', $order->id);
            $notify = [
                'uid'     => $user->id,
                'type'    => 1,
                'content' => '下单成功，订单号：' . $order->sn,
                'source'  => $order->id
            ];
            Event::trigger('UserNotify', $notify);
            parent::commit();
            Cache::set('nowOrderId_' . $user->id, null);
            return ['code' => 1, 'msg' => '支付成功', 'url' => url('order/my_order')->build()];
        } catch (\Exception $e) {
            parent::rollback();
            return ['code' => -1, 'msg' => $e->getMessage()];
        }

    }

    /**
     * @param $param
     * @param $user
     * @return array
     * 原点 2022年1月8日16:43:09 订单相关操作
     */
    public static function edit($param, $user): array
    {
        try {
            $info = parent::where(['id' => $param['id'], 'uid' => $user->id, 'is_del' => 0])->find();
            if (empty($info)) {
                return ['code' => -1, 'msg' => '订单不存在'];
            }
            switch ($param['type']) {
                case 'clear': //取消订单
                    if ($info->getData('status') != 1 || $info->pay_state) {
                        return ['code' => -1, 'msg' => '订单已支付，无法取消'];
                    }
                    $info->is_del = 1;
                    $info->status = 6;
                    $info->cancel_time = time();
                    $info->save();
                    return ['code' => 1, 'msg' => '订单已取消'];
                case 'payment': //支付订单
                    if ($info->getData('status') != 1) {
                        return ['code' => -1, 'msg' => '订单已支付'];
                    }
                    Cache::set('nowOrderId_' . $user->id, $info->id);
                    return ['code' => 4, 'msg' => '已生成订单', 'url' => url('order/payment')->build()];

                case "remind": //提醒发货
                    if ($info->getData('status') != 2) {
                        return ['code' => -1, 'msg' => '订单未支付或已发货'];
                    }
                    if ($info->is_remind) {
                        return ['code' => -1, 'msg' => '您已提醒发货了！'];
                    }
                    $info->is_remind = 1;
                    $info->remind_time = time();
                    $info->save();
                    return ['code' => 1, 'msg' => '已提醒发货'];
                case "receipt": //确认收货
                    if ($info->getData('status') != 3) {
                        return ['code' => -1, 'msg' => '订单异常'];
                    }
                    $info->status = 4;
                    $info->receipt_time = time();
                    $info->save();
                    return ['code' => 1, 'msg' => '已确认收货'];
                default:
                    return ['code' => -1, 'msg' => '加载失败'];

            }
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

}
